package com.huatai.exchange.impl;

import com.faneui.common.exception.BusinessException;
import com.faneui.common.utils.Constants;
import com.faneui.common.utils.DateFormatUtils;
import com.faneui.common.utils.ListUtils;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.huatai.exchange.AbstractService;
import com.huatai.exchange.cache.FileLoadInfoCache;
import com.huatai.exchange.dal.model.*;
import com.huatai.exchange.deal.FileCreateDealFactory;
import com.huatai.exchange.facade.Contents;
import com.huatai.exchange.facade.enums.ComplexityTypeEnum;
import com.huatai.exchange.integration.base.service.FileOperateService;
import com.huatai.exchange.load.DataFileLoadFactory;
import com.huatai.exchange.receive.FileDataReceiveFactory;
import com.huatai.exchange.send.FileSendFactory;
import com.huatai.exchange.send.FileSendService;
import com.huatai.exchange.service.*;
import com.huatai.exchange.utils.VelocityContextHelper;
import com.huatai.exchange.utils.VelocityUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.File;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@Service
public class ExcuteExchangeServiceImpl extends AbstractService implements ExcuteExchangeService {

    private static final Logger logger = LoggerFactory.getLogger(ExcuteExchangeService.class);

    @Autowired
    private ExcExchangeInfoService excExchangeInfoService;

    @Autowired
    protected FileOperateService fileOperateService;

    @Autowired
    private ExcExchangeDataFileService excExchangeDateFileService;

    @Autowired
    private ExcDataFileInfoService excDataFileInfoService;

    @Autowired
    private VelocityContextHelper velocityHelper;

    @Autowired
    private FileCreateDealFactory dealFactory;

    @Autowired
    private FileDataReceiveFactory fileDataReceiveFactory;

    @Autowired
    private DataFileLoadFactory dataFileLoadFactory;

    @Autowired
    private FileSendFactory fileSendFactory;

    @Autowired
    private ExcFileLoadRecordService excFileLoadRecordService;

    @Autowired
    private ExcFileLoadInfoService excFileLoadInfoService;

    @Value("${tmp_file_path}")
    private String tmpFileBasePath;

    @Value("${night_file_backup_url}")
    private String backupUrl;

    @Override
    public void executeExchangeDataFile(ExcCustDataFile custDataFile, String occurDate, Map<String, Object> resvMap) throws BusinessException {
        try {
            FileSendService sendService = fileSendFactory.getSendService(custDataFile.getDestType());
            // check 通讯是否完成
            sendService.checkCommunicationIsFinish((String) resvMap.get("businId"));

            ExcExchangeInfo exchangeInfo = excExchangeInfoService.queryExcExchangeInfo(custDataFile.getExchangeInfoId());

            //此代码测试净值发送偶发的日期问题
            logger.info("###BeforecheckIsAllowExc_1###CustId=" + custDataFile.getId() + "_" + custDataFile.getCustName() + " before_occurDate:" +  occurDate);


            //  resvMap 上下文 信息共享
            resvMap.put(Contents.FIELD_YYYYMMDD, occurDate);

            resvMap.put("exchangeInfoId", custDataFile.getExchangeInfoId());

            Velocity.init();
            VelocityContext context = velocityHelper.fillContext(resvMap);

            //此代码测试净值发送偶发的日期问题
            logger.info("###BeforecheckIsAllowExc_2###CustId=" + custDataFile.getId() + "_" + custDataFile.getCustName() + " before_map_occurDate:" +  resvMap.get(Contents.FIELD_YYYYMMDD));


            String beforeContent = exchangeInfo.getBeforeContent();
            // check menthod is allow
            checkIsAllowExc(context, beforeContent);
            // 设置文件回收机制，否则 会有很多垃圾文件
            resvMap.put(Contents.FILE_GC, "");
            getAndLoadFileList(custDataFile, context, resvMap);

            VelocityUtils.evaluate(context, exchangeInfo.getContent());

            //此代码测试净值发送偶发的日期问题
            logger.info("###BeforecheckIsAllowExc_3###CustId=" + custDataFile.getId() + "_" + custDataFile.getCustName() + " after_map_occurDate:" +  resvMap.get(Contents.FIELD_YYYYMMDD));

            // 多种传输方式

            //目标地址变量赋值
            String destAddress = custDataFile.getDestAddress();
            destAddress = formatStr(destAddress, resvMap);

            sendService.sendMessage(destAddress, resvMap);
            // 传输后处理

        } catch (Exception ex) {
            BusinessException.throwBusinessException(ex);
        } finally {
            // 删除已经存在好的文件
            // 别删了模板文件
            String filePaths = (String) resvMap.get(Contents.FILE_GC);
            if (StringUtils.isNotBlank(filePaths)) {
                String[] paths = filePaths.split(",");
                for (String path : paths) {
                    if (StringUtils.isNotBlank(path))
                        new File(path).deleteOnExit();
                }
            }
        }
    }


    private void checkIsAllowExc(VelocityContext context, String content) throws BusinessException {
        if (StringUtils.isNotBlank(content)) {
            try {
                String checkResult = VelocityUtils.evaluate(context, content);
                // 交换校验指标 需要在这里标识
                if (!com.faneui.common.utils.Constants.boolean_true.equals(checkResult)) {
                    throw new BusinessException(checkResult);
                }
            } catch (Exception ex) {
                BusinessException.throwBusinessException(ex);
            }
        }
    }

    private void getAndLoadFileList(ExcCustDataFile custDataFile, VelocityContext context, Map<String, Object> resvMap) throws BusinessException {
        logger.info("=============={}=============", "开始准备文件");
        resvMap.put("FILE_NUM", "0");
        List<ExcExchangeDataFile> dataFileList = excExchangeDateFileService.queryExcExchangeDateFileListByCustDataFileId(custDataFile.getId());
        if (ListUtils.isEmpty(dataFileList))
            return;
        StringBuffer fileNames = new StringBuffer("");
        StringBuffer filePaths = new StringBuffer("");
        //  遍历数据文件信息，获取文件
        boolean b = StringUtils.isNotBlank(custDataFile.getComplexity())
                && !ComplexityTypeEnum.simple.getCode().equals(custDataFile.getComplexity());
        for (ExcExchangeDataFile dateFile : dataFileList) {
            ExcDataFileInfo dataFileInfo = excDataFileInfoService.queryExcDataFileInfo(dateFile.getDataFileId());
            if (dataFileInfo == null)
                throw new BusinessException("数据文件ID[" + dateFile.getDataFileId() + "]配置信息不存在");
            if (b) {

            }
            // velocity check file can create
            checkIsAllowExc(context, dataFileInfo.getCheckContent());
            // create file
            dealFactory.getDealService(dataFileInfo.getType()).downloadCreateFile(fileNames, filePaths, dataFileInfo, resvMap);
        }
        logger.info("完成文件准备：" + DateFormatUtils.HHmmss.format(new Date()));
        // 压缩设置
        if (StringUtils.isBlank(filePaths.toString())) {
            return;
        }
        String zipFileName = (String) resvMap.get(Contents.FIELD_ZIPFILENAME);
        if (StringUtils.isNotBlank(zipFileName)) {
            String zipFilePath;
            if (zipFileName.contains(".rar")) {
                zipFilePath = fileOperateService.uploadRarFiles(filePaths.toString().substring(1), fileNames.toString().substring(1), com.faneui.common.utils.Constants.boolean_false);
            } else {
                zipFilePath = fileOperateService.uploadZipFiles(filePaths.toString().substring(1), fileNames.toString().substring(1), com.faneui.common.utils.Constants.boolean_false);
            }
            logger.info("重新压缩文件：" + DateFormatUtils.HHmmss.format(new Date()));
            String zipfileName = formatStr(zipFileName, resvMap);
            resvMap.put("fileNames", zipfileName);
            resvMap.put("filePaths", zipFilePath);
        } else {
            resvMap.put("fileNames", fileNames.toString().substring(1));
            resvMap.put("filePaths", filePaths.toString().substring(1));
        }
        resvMap.put("FILE_NUM", resvMap.get("fileNames").toString().split(",").length);
    }

    @Override
    public void executeLoadDataFile(String fileId, String occurDate) throws BusinessException {
        ExcFileLoadRecord record = excFileLoadRecordService.queryExcFileLoadRecord(fileId, occurDate);
        if (record != null) {
            logger.info("文件【" + FileLoadInfoCache.loadFileNameCache.get(fileId) + "】日期" + occurDate + "已存在");
            return;
        }
        ExcFileLoadInfo loadInfo = excFileLoadInfoService.queryExcFileLoadInfo(fileId);
        if(loadInfo == null) {
            throw new BusinessException("配置错误，备份文件信息不存在");
        }
        Map<String, Object> resvMap = Maps.newHashMap();
        resvMap.put("YYYYMMDD", occurDate);
        // 临时文件夹，存放下载后的文件
        String tmpDirPath = tmpFileBasePath + UUID.randomUUID().toString() + "/";
        try {

            // 接收下来的文件列表
            List<String> fileNames = fileDataReceiveFactory
                    .getReceiveService(loadInfo.getCommunicationType())
                    .receiveMessage(loadInfo, tmpDirPath, resvMap);

            String fileName = "-";
            // 有可能当天 没有文件的
            if (ListUtils.isEmpty(fileNames)) {
                // 可为空
                if (Constants.boolean_true.equals(loadInfo.getIsNullAble())) {
                    throw new BusinessException("文件不存在");
                }
            } else {
                // 存储后的文件名称
                fileName = dataFileLoadFactory.getLoadService(loadInfo.getFileSuffix())
                        .loadDataFile(loadInfo, tmpDirPath, fileNames, resvMap);
            }
            record = new ExcFileLoadRecord();
            record.setOccurDate(occurDate);
            record.setLoadId(loadInfo.getId());
            record.setFilePath(fileName);
            excFileLoadRecordService.addExcFileLoadRecord(record);

        } catch (Exception ex) {
            BusinessException.throwBusinessException(ex);
        } finally {
            new File(tmpDirPath).deleteOnExit();
        }

    }

    @Override
    public void reLoadDataFile(String filePath, String recordId) throws BusinessException {
        ExcFileLoadRecord record = excFileLoadRecordService.queryExcFileLoadRecord(recordId);

        ExcFileLoadInfo loadInfo = excFileLoadInfoService.queryExcFileLoadInfo(record.getLoadId());

        String tmpDirPath = tmpFileBasePath + UUID.randomUUID().toString() + "/";
        Map<String, Object> resvMap = Maps.newHashMap();
        resvMap.put("YYYYMMDD", record.getOccurDate());
        try {

            String path = dataFileLoadFactory.getLoadService(loadInfo.getFileSuffix()).loadDataFile(loadInfo, tmpDirPath, Lists.newArrayList(filePath), resvMap);
            record.setFilePath(path);

        } catch (Exception ex) {
            BusinessException.throwBusinessException(ex);
        } finally {
            new File(tmpDirPath).deleteOnExit();
        }
    }
}
